#include <iostream>
#include <sstream>
#include <string>
#include <memory>
#include <ctime>
#include <unistd.h>
#include "Socket.hpp"
#include "Protocol.hpp"
#include "Calculator.hpp"
#include "Factory.hpp"
using namespace std;



int main(int argc, char *argv[])
{
    srand(time(nullptr) ^ getpid());
    if (argc != 3)
    {
        cout << "Incorrect use: " << endl
             << "    " << argv[0] << "ip port" << endl;
        return 1;
    }

    string serverip = argv[1];
    uint16_t serverport = stoi(argv[2]);
    Protocol pro;
    unique_ptr<Factory> ft(new Factory());

    unique_ptr<Socket> up(new TcpSocket());
    if (!up->BuildClientFSock(serverip, serverport))
        cout << "create client sockfd: " << up->GetSockFd() << endl;

    while (true)
    {
        int x = rand() % 100;
        int y = rand() % 100;
        char op = opers[rand() % opers.size()];
        // 1. 构造请求
        shared_ptr<Calculator::Request> req = ft->BuildRequest(x, y, op);

        string request;
        // 2. 请求序列化
        req->Serialize(&request);
        string message;
        // 3. 将序列化请求封装成报文
        pro.Package(request, &message);
        // cout << "报文：" << request << endl;
        // 4. 发送报文
        up->Send(message);

        // 5. 接收报文
        string response;
        if(!up->Recv(response, 4096)) cout << "读取错误" << endl;
        // 6. 报文解包
        string content;
        pro.Unpacking(response, &content);

        // 内容反序列化
        shared_ptr<Calculator::Response> res = ft->BuildResponse();
        bool ok;
        res->Deserialize(content, &ok);
        if (ok)
        {
            cout << req->GetX() << " " << req->GetOp() << " " << req->GetY() << " = " << res->GetResult() << "[" << res->GetCode() << "]" << endl;
        }
        else
            break;
    }

    up->CloseSockFd();
    return 0;
}